<template>
  <a-modal v-model:open="visible" :title="file?.originalName || '文件预览'" width="90%" :style="{ top: '20px' }" :footer="null" :destroyOnClose="true" @cancel="handleClose">
    <div class="file-preview-container">
      <!-- 加载状态 -->
      <div v-if="loading" class="preview-loading">
        <a-spin size="large" />
        <p>正在加载预览...</p>
      </div>

      <!-- 错误状态 -->
      <div v-else-if="error" class="preview-error">
        <exclamation-circle-outlined class="error-icon" />
        <p>{{ error }}</p>
        <a-button type="primary" @click="handleDownload">
          <template #icon><download-outlined /></template>
          下载文件
        </a-button>
      </div>

      <!-- Word文档预览 -->
      <div v-else-if="previewType === 'word'" class="preview-content office-preview">
        <vue-office-docx v-if="fileBlob" :src="fileBlob" @rendered="onDocxRendered" @error="onDocxError" style="height: calc(100vh - 280px); overflow: auto" />
      </div>

      <!-- Excel表格预览 -->
      <div v-else-if="previewType === 'excel'" class="preview-content office-preview">
        <vue-office-excel v-if="fileBlob" :src="fileBlob" @rendered="onExcelRendered" @error="onExcelError" style="height: calc(100vh - 280px)" />
      </div>

      <!-- PDF预览 -->
      <div v-else-if="previewType === 'pdf'" class="preview-content office-preview">
        <vue-office-pdf v-if="fileBlob" :src="fileBlob" @rendered="onPdfRendered" @error="onPdfError" style="height: calc(100vh - 280px)" />
      </div>

      <!-- 文本文件预览 -->
      <div v-else-if="previewType === 'text'" class="preview-content text-preview">
        <pre>{{ textContent }}</pre>
      </div>

      <!-- 图片预览 -->
      <div v-else-if="previewType === 'image'" class="preview-content image-preview">
        <img :src="previewUrl" :alt="file?.originalName" />
      </div>

      <!-- 不支持的格式 -->
      <div v-else class="preview-unsupported">
        <file-outlined class="unsupported-icon" />
        <p>此文件格式暂不支持在线预览</p>
        <a-button type="primary" @click="handleDownload">
          <template #icon><download-outlined /></template>
          下载文件查看
        </a-button>
      </div>
    </div>

    <!-- 底部操作栏 -->
    <div class="preview-footer">
      <a-space>
        <a-button @click="handleDownload">
          <template #icon><download-outlined /></template>
          下载文件
        </a-button>
      </a-space>
    </div>
  </a-modal>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { message } from 'ant-design-vue'
import { ExclamationCircleOutlined, DownloadOutlined, FileOutlined } from '@ant-design/icons-vue'
// 导入 vue-office 组件
import VueOfficeDocx from '@vue-office/docx'
import VueOfficeExcel from '@vue-office/excel'
import VueOfficePdf from '@vue-office/pdf'
// 导入样式
import '@vue-office/docx/lib/index.css'
import '@vue-office/excel/lib/index.css'

import { API_BASE_URL } from '@/utils/api'
import { useFileStorageStore } from '@/stores/fileStorage'

// Props
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  file: {
    type: Object,
    default: null
  }
})

// Emits
const emit = defineEmits(['update:modelValue'])

// Store
const fileStorageStore = useFileStorageStore()

// 响应式数据
const loading = ref(false)
const error = ref('')
const textContent = ref('')
const previewUrl = ref('')
const fileBlob = ref(null)

// 计算属性
const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

// 获取预览类型
const previewType = computed(() => {
  if (!props.file) return null

  const mimeType = props.file.mimeType?.toLowerCase() || ''
  const fileName = props.file.originalName?.toLowerCase() || ''

  // Word文档
  if (mimeType.includes('word') || mimeType.includes('msword') || mimeType.includes('officedocument.wordprocessing') || fileName.endsWith('.doc') || fileName.endsWith('.docx')) {
    return 'word'
  }

  // Excel表格
  if (mimeType.includes('excel') || mimeType.includes('spreadsheet') || mimeType.includes('ms-excel') || mimeType.includes('officedocument.spreadsheet') || fileName.endsWith('.xls') || fileName.endsWith('.xlsx')) {
    return 'excel'
  }

  // PDF
  if (mimeType.includes('pdf') || fileName.endsWith('.pdf')) {
    return 'pdf'
  }

  // 文本文件
  if (mimeType.includes('text') || fileName.endsWith('.txt') || fileName.endsWith('.log') || fileName.endsWith('.md') || fileName.endsWith('.json') || fileName.endsWith('.xml') || fileName.endsWith('.csv')) {
    return 'text'
  }

  // 图片
  if (mimeType.includes('image')) {
    return 'image'
  }

  return null
})

// 获取文件URL
const getFileUrl = () => {
  if (!props.file) return ''
  // 使用下载接口，确保有正确的认证
  return `${API_BASE_URL}/file-storage/download/${props.file.id}`
}

// 加载预览内容
const loadPreview = async () => {
  if (!props.file) return

  loading.value = true
  error.value = ''
  fileBlob.value = null

  try {
    switch (previewType.value) {
      case 'word':
      case 'excel':
      case 'pdf':
        await loadFileBlob()
        break

      case 'text':
        await loadTextContent()
        break

      case 'image':
        previewUrl.value = getFileUrl()
        break

      default:
        error.value = '不支持的文件格式'
    }
  } catch (err) {
    console.error('加载预览失败:', err)
    error.value = '加载预览失败，请尝试下载文件查看'
  } finally {
    loading.value = false
  }
}

// 加载文件Blob用于Office组件
const loadFileBlob = async () => {
  try {
    const response = await fetch(getFileUrl(), {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('token')}`
      }
    })

    if (!response.ok) {
      throw new Error('加载文件失败')
    }

    const blob = await response.blob()

    // vue-office 组件支持 blob 和 ArrayBuffer
    // 对于 docx 和 excel，使用 ArrayBuffer 更稳定
    const arrayBuffer = await blob.arrayBuffer()
    fileBlob.value = arrayBuffer
  } catch (err) {
    console.error('加载文件Blob失败:', err)
    throw err
  }
}

// 加载文本内容
const loadTextContent = async () => {
  try {
    const response = await fetch(getFileUrl(), {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('token')}`
      }
    })

    if (!response.ok) {
      throw new Error('加载文件失败')
    }

    const text = await response.text()
    textContent.value = text
  } catch (err) {
    console.error('加载文本内容失败:', err)
    throw err
  }
}

// 下载文件
const handleDownload = async () => {
  try {
    await fileStorageStore.downloadFileData(props.file)
    message.success('文件下载开始')
  } catch (err) {
    message.error('文件下载失败')
  }
}

// Word文档渲染回调
const onDocxRendered = () => {
  console.log('Word文档渲染完成')
  loading.value = false
}

const onDocxError = (err) => {
  console.error('Word文档预览失败:', err)
  error.value = 'Word文档预览失败，请下载文件查看'
  loading.value = false
}

// Excel表格渲染回调
const onExcelRendered = () => {
  console.log('Excel表格渲染完成')
  loading.value = false
}

const onExcelError = (err) => {
  console.error('Excel表格预览失败:', err)
  error.value = 'Excel表格预览失败，请下载文件查看'
  loading.value = false
}

// PDF渲染回调
const onPdfRendered = () => {
  console.log('PDF文档渲染完成')
  loading.value = false
}

const onPdfError = (err) => {
  console.error('PDF文档预览失败:', err)
  error.value = 'PDF文档预览失败，请下载文件查看'
  loading.value = false
}

// 关闭预览
const handleClose = () => {
  visible.value = false
  // 清理状态
  textContent.value = ''
  previewUrl.value = ''
  fileBlob.value = null
  error.value = ''
}

// 监听文件变化
watch(
  () => props.file,
  (newFile) => {
    if (newFile && visible.value) {
      loadPreview()
    }
  },
  { immediate: true }
)

// 监听打开状态
watch(visible, (newVal) => {
  if (newVal && props.file) {
    loadPreview()
  }
})
</script>

<style scoped>
.file-preview-container {
  min-height: 500px;
  max-height: calc(100vh - 200px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.preview-loading,
.preview-error,
.preview-unsupported {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  color: #8c8c8c;
}

.preview-loading p,
.preview-error p,
.preview-unsupported p {
  margin: 16px 0;
  font-size: 16px;
}

.error-icon,
.unsupported-icon {
  font-size: 64px;
  color: #ff4d4f;
}

.unsupported-icon {
  color: #d9d9d9;
}

.preview-content {
  flex: 1;
  overflow: auto;
  background: #f5f5f5;
  border-radius: 4px;
  padding: 16px;
}

.office-preview {
  background: #fff;
  padding: 0;
}

.text-preview {
  background: #fff;
  border: 1px solid #e8e8e8;
}

.text-preview pre {
  margin: 0;
  padding: 16px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: #262626;
}

.image-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  padding: 0;
}

.image-preview img {
  max-width: 100%;
  max-height: calc(100vh - 250px);
  object-fit: contain;
}

.preview-footer {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #f0f0f0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* vue-office 组件样式覆盖 */
:deep(.docx-wrapper) {
  padding: 20px;
  background: #fff;
}

:deep(.excel-wrapper) {
  background: #fff;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .image-preview img {
    max-height: 400px;
  }
}
</style>
